﻿using IOP.Pulsar.Abstractions;
using IOP.Pulsar.Hosting;
using IOP.Pulsar.Server;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using IOP.Pulsar.Options;

namespace IOP.Pulsar.Extensions
{
    /// <summary>
    /// 主机扩展
    /// </summary>
    public static class HostExtension
    {

        /// <summary>
        /// 配置脉冲星主机
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="configure"></param>
        /// <returns></returns>
        public static IHostBuilder ConfigurePulsarHost(this IHostBuilder builder, Action<IPulsarHostBuilder> configure)
        {
            IPulsarHostBuilder pulsar = null;
            builder.ConfigureServices((context, services) =>
            {
                pulsar = new PulsarHostBuilder(services, context);
                configure(pulsar);
                pulsar.Build();
            });
            return builder;
        }

        /// <summary>
        /// 添加TCP服务器
        /// </summary>
        /// <typeparam name="TContext"></typeparam>
        /// <param name="builder"></param>
        /// <param name="serverName"></param>
        /// <returns></returns>
        public static IPulsarHostBuilder AddTCPServer<TContext>(this IPulsarHostBuilder builder, string serverName)
            where TContext : class
        {
            return builder.ConfigureServices((context, services) =>
            {
                services.AddSingleton<ISocketPool, SocketPool>();
                services.AddSingleton(typeof(IHostedService), (factory) =>
                {
                    TCPServerOption option = new TCPServerOption();
                    option.ServerName = serverName;
                    var config = factory.GetRequiredService<IConfiguration>();
                    var life = factory.GetRequiredService<IHostLifetime>();
                    var logger = factory.GetRequiredService<ILogger<TCPServer<TContext>>>();
                    var store = factory.GetRequiredService<ISocketPool>();
                    return new TCPServer<TContext>(logger, config, life, factory, store, option);
                });
            });
        }

        /// <summary>
        /// 添加TCP服务器
        /// </summary>
        /// <typeparam name="TContext"></typeparam>
        /// <param name="builder"></param>
        /// <param name="option"></param>
        /// <returns></returns>
        public static IPulsarHostBuilder AddTCPServer<TContext>(this IPulsarHostBuilder builder, Action<TCPServerOption> option)
            where TContext : class
        {
            return builder.ConfigureServices((context, services) =>
            {
                services.AddSingleton<ISocketPool, SocketPool>();
                services.AddSingleton(typeof(IHostedService), (factory) =>
                {
                    TCPServerOption tOption = new TCPServerOption();
                    option?.Invoke(tOption);
                    var config = factory.GetRequiredService<IConfiguration>();
                    var life = factory.GetRequiredService<IHostLifetime>();
                    var logger = factory.GetRequiredService<ILogger<TCPServer<TContext>>>();
                    var store = factory.GetRequiredService<ISocketPool>();
                    return new TCPServer<TContext>(logger, config, life, factory, store, tOption);
                });
            });
        }

        /// <summary>
        /// 添加RawSocket服务器
        /// </summary>
        /// <typeparam name="TContext"></typeparam>
        /// <param name="builder"></param>
        /// <param name="serverName"></param>
        /// <returns></returns>
        public static IPulsarHostBuilder AddRawSocketServer<TContext>(this IPulsarHostBuilder builder, string serverName)
            where TContext : class
        {
            return builder.ConfigureServices((context, services) =>
            {
                services.AddSingleton(typeof(IHostedService), (factory) =>
                {
                    RawSocketServerOption option = new RawSocketServerOption();
                    option.ServerName = serverName;
                    var config = factory.GetRequiredService<IConfiguration>();
                    var life = factory.GetRequiredService<IHostLifetime>();
                    var logger = factory.GetRequiredService<ILogger<RawSocketServer<TContext>>>();
                    return new RawSocketServer<TContext>(logger, config, life, factory, option);
                });
            });
        }

        /// <summary>
        /// 使用启动项
        /// </summary>
        /// <typeparam name="TStartup"></typeparam>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static IPulsarHostBuilder UseStartup<TStartup>(this IPulsarHostBuilder builder)
            where TStartup : class, IStartup
        {
            return builder.ConfigureServices((hostContext, services) =>
            {
                services.AddSingleton<IStartup, TStartup>();
                services.AddSingleton<IServerBuilder, ServerBuilder>();
            });
        }
    }
}
